package com.freestyle.multidatasource;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by rocklee on 2021/2/5 10:26
 *

不用啦!@Component, 应用失败, 只能根据不同的datasource动态生成SqlSession实例,再从此实例中取出mapper,利用database自有的事务管理,而spring的事务管理器不生效不知道为何.
 具体见com.alco.bms.modules.syncdata.service.TransactionLogSynchronizeImpl#synchronizeDataToServer_(com.alco.bms.modules.syncdata.pojo.TransactionLogData, com.alco.appconfig.BMSConfig.DBServerConfig)
 */
@Deprecated
//@Component
public class TransactionManagerRegister implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
  private static Map<String, PlatformTransactionManager> transactionManagerMap=new HashMap<>();
  private ApplicationContext applicationContext;
  public static PlatformTransactionManager getTransactionManager(String key){
    return transactionManagerMap.get(key);
  }
  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    for (Map.Entry<String,DataSource> entry:DataSourceRegister.getCustomDataSources().entrySet()) {
      DataSourceTransactionManager ptm=new DataSourceTransactionManager(entry.getValue());
      ptm.setNestedTransactionAllowed(true);
      transactionManagerMap.put("tm_"+entry.getKey(),ptm);
    }
    //if (1+1==2) return; //因为存在多个DataSourceTransactionManager实例的时候,要用@Transactional就必须指定transactionManager别名!所以还是放弃把这些管理器放到spring容器中


    // 手动注册的Bean类型 ， 由于我要注册的其实是 接口的实现类
    // 所以采用FactoryBean方式创建Bean
    // 若仅仅需要对Bean注入值，可以直接指定想创建的Bean的class
    for (Map.Entry<String,DataSource> entry:DataSourceRegister.getCustomDataSources().entrySet()) {
      BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(DataSourceTransactionManager.class);
      AbstractBeanDefinition definition = builder.getRawBeanDefinition();
      //亦可通过setBeanClass方式指定创建的类
      //definition.setBeanClass(TestFactory.class);
      MutablePropertyValues mpv=definition.getPropertyValues();
      mpv.addPropertyValue("dataSource", entry.getValue()); //set 方式autowired，需要指定属性有set方法
      mpv.addPropertyValue("nestedTransactionAllowed", true);
      // 构造方法autowired，FactoryBean 的 construct 方法必须有 ， 两种注入方式选其一
      // definition.getConstructorArgumentValues().addGenericArgumentValue();
      // 对 TestFactory 中的所有属性默认使用 byType 的依赖注入，若同一class有多个bean，则会报错。
      definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
      registry.registerBeanDefinition("tm_"+entry.getKey(), definition);
    }
  }

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext=applicationContext;
  }
}
